﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FBGraph.ClientGenerator.CodeGen;

namespace FBGraph.ClientGenerator.Tests.CodeGen
{
    [TestClass]
    public class CodeGenTypeTests
    {
        [TestMethod]
        public void OutputDeclaration()
        {
            var testClass = new CodeGenType("TestClass", "FBGraph.Models");
            testClass.InterfaceImplementations.Suggest(typeof(IFBGraphResult));

            var expected =
@"using System;

namespace FBGraph.Models
{
    public partial class TestClass : IFBGraphResult
    {
    }
}".ReplaceTabs();

            var actual = testClass.ToString();

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void OutputAllTogetherNow()
        {
            var testClass = new CodeGenType("TestClass", "FBGraph.Models");
            testClass.InheritFrom(new TypeReference("SomeBaseClass", new TypeReference(typeof(Int32))));
            testClass.TypeArguments.Add(new TypeReference(typeof(String)));
            testClass.TypeArguments.Add(new TypeReference(typeof(Int32)));

            testClass.XmlDocComments.Suggest("<summary>This is a test class</summary>");

            testClass.InterfaceImplementations.Suggest(new TypeReference(typeof(IFBGraphResult)));
            testClass.InterfaceImplementations.Suggest(new TypeReference("ISomeOtherInterface", new TypeReference(typeof(String))));

            testClass.Imports.Suggest("System.Runtime.Serialization");
            testClass.CustomAttributes.Suggest("DataContract", new NamedArgument("Name", "testClass"));

            var ctr = new Constructor(testClass, new Parameter("foo", typeof(String)))
            {
                ChainedConstructor = new ChainedConstructor("base", "foo")
            };
            ctr.XmlDocComments.Suggest("<summary>Initializes an instance of <see cref=\"TestClass\" />.</summary>");
            ctr.XmlDocComments.Suggest("<param name=\"foo\">A <see cref=\"String\" /> value representing the foo.</param>");
            testClass.Constructors.Suggest(ctr);

            var fooProperty = new AutoProperty("Foo", typeof(String))
            {
                SetAccessibility = "protected"
            };
            fooProperty.CustomAttributes.Suggest("DataMember", new NamedArgument("Name", "foo"));
            fooProperty.XmlDocComments.Suggest("<summary>Gets the value of foo.</summary>");
            testClass.Properties.Suggest(fooProperty);

            var connectionNameProperty = new Property("ConnectionName", typeof(String))
            {
                HasGet = true,
                GetBody = "return \"Foo\";"
            };
            connectionNameProperty.XmlDocComments.Suggest("<summary>Gets the connection name.</summary>");
            testClass.Properties.Suggest(connectionNameProperty);

            var nestedClass = testClass.GetNestedType("SomeNestedClass");
            nestedClass.XmlDocComments.Suggest("<summary>Encapsulates nested foo data</summary>");
            var nestedFooProperty = new AutoProperty("Foo", typeof(String));
            nestedFooProperty.XmlDocComments.Suggest("<summary>Gets or sets the foo.</summary>");
            nestedClass.Properties.Suggest(nestedFooProperty);

            var expected = ExpectedSamples.CodeGenType.ReplaceTabs();
            var actual = testClass.ToString();

            var expectedLines = expected.Split(new String[] { Environment.NewLine }, StringSplitOptions.None);
            var actualLines = actual.Split(new String[] { Environment.NewLine }, StringSplitOptions.None);

            for (var i = 0; i < (expectedLines.Length > actualLines.Length ? actualLines.Length : expectedLines.Length); i++)
            {
                Assert.AreEqual(expectedLines[i], actualLines[i]);
            }

            Assert.AreEqual(expectedLines.Length, actualLines.Length);
            Assert.AreEqual(expected, actual);
        }
    }
}